package com.ruoyi.riskrule.config;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.bizsys.domain.CustomerCrsReport;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.Func;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.riskrule.config.common.RuleUtils;
import com.ruoyi.riskrule.domain.RuleInNextStepCrs;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author mac
 */
@Slf4j
public class CrsWriteFactory {


    public Object setCrs(RuleInNextStepCrs ruleInNextStep, CustomerCrsReport ctcustomerCrsReport) {

        JSONObject performanceSummary = JSONObject.parseObject(ctcustomerCrsReport.getPerformanceSummary());

        if (performanceSummary != null) {
            ruleInNextStep.setCrsinquirycount12months(performanceSummary.getString("Inquiry_Count_12_Months"));
            ruleInNextStep.setCrscountaccountstatusclosed(performanceSummary.getString("Count_AccountStatus_Closed"));
            ruleInNextStep.setCrscountaccountstatusdelinquent30over60days(performanceSummary.getString("Count_AccountStatus_Delinquent_30_over_60_days"));
            ruleInNextStep.setCrscountaccountstatusderogatory120days(performanceSummary.getString("Count_AccountStatus_Derogatory_120_days"));
            ruleInNextStep.setCrscountaccountstatusderogatory150days(performanceSummary.getString("Count_AccountStatus_Derogatory_150_days"));
            ruleInNextStep.setCrscountaccountstatusderogatorydoubtful180(performanceSummary.getString("Count_AccountStatus_Derogatory_Doubtful_180"));
            ruleInNextStep.setCrscountaccountstatusderogatorylost360(performanceSummary.getString("Count_AccountStatus_Derogatory_Lost_360"));
            ruleInNextStep.setCrscountaccountstatusderogatorysubstandard90(performanceSummary.getString("Count_AccountStatus_Derogatory_Substandard_90"));
            ruleInNextStep.setCrscountaccountstatuslatelessthan30days(performanceSummary.getString("Count_AccountStatus_Late_less_than_30_days"));
            ruleInNextStep.setCrscountaccountstatusopen(performanceSummary.getString("Count_AccountStatus_Open"));
            ruleInNextStep.setCrscountaccountstatusperforming(performanceSummary.getString("Count_AccountStatus_Performing"));
            ruleInNextStep.setCrscountaccountstatusunknown(performanceSummary.getString("Count_AccountStatus_Unknown"));
            ruleInNextStep.setCrscountaccountstatusunspecified(performanceSummary.getString("Count_AccountStatus_Unspecified"));
            ruleInNextStep.setCrscountaccountstatuswrittenoff(performanceSummary.getString("Count_AccountStatus_Written_off"));
            ruleInNextStep.setCrscountlegalstatusjudgment(performanceSummary.getString("Count_LegalStatus_Judgment"));
            ruleInNextStep.setCrscountlegalstatuslitigation(performanceSummary.getString("Count_LegalStatus_Litigation"));
            ruleInNextStep.setCrscountlegalstatusnotice(performanceSummary.getString("Count_LegalStatus_Notice"));
            ruleInNextStep.setCrscountlegalstatusreceivership(performanceSummary.getString("Count_LegalStatus_Receivership"));
            ruleInNextStep.setCrsselfinquirieslast12months(performanceSummary.getString("SelfInquiriesLast12Months"));
            ruleInNextStep.setCrsdishonouredchequeslast12months(performanceSummary.getString("DishonouredChequesLast12Months"));
        }

        JSONArray accountSummariesArray = JSONArray.parseArray(ctcustomerCrsReport.getAccountSummaries());
        if (accountSummariesArray != null) {
            for (int i = 0; i < accountSummariesArray.size(); i++) {
                JSONObject accountSummaries = accountSummariesArray.getJSONObject(i);
                if (accountSummaries != null && "NGN".equals(accountSummaries.getString("Currency"))) {
                    ruleInNextStep.setCrsaccountsummariesbalanceinstallment(accountSummaries.getString("Balance_Installment"));
                    ruleInNextStep.setCrsaccountsummariesbalanceauto(accountSummaries.getString("Balance_Auto"));
                    ruleInNextStep.setCrsaccountsummariesbalancemortgage(accountSummaries.getString("Balance_Mortgage"));
                    ruleInNextStep.setCrsaccountsummariesbalanceother(accountSummaries.getString("Balance_Other"));
                    ruleInNextStep.setCrsaccountsummariesbalanceoverdraft(accountSummaries.getString("Balance_Overdraft"));
                    ruleInNextStep.setCrsaccountsummariesbalancerevolving(accountSummaries.getString("Balance_Revolving"));
                    ruleInNextStep.setCrsaccountsummariescountinstallment(accountSummaries.getString("Count_Installment"));
                    ruleInNextStep.setCrsaccountsummariescountauto(accountSummaries.getString("Count_Auto"));
                    ruleInNextStep.setCrsaccountsummariescountmortgage(accountSummaries.getString("Count_Mortgage"));
                    ruleInNextStep.setCrsaccountsummariescountother(accountSummaries.getString("Count_Other"));
                    ruleInNextStep.setCrsaccountsummariescountoverdraft(accountSummaries.getString("Count_Overdraft"));
                    ruleInNextStep.setCrsaccountsummariescountrevolving(accountSummaries.getString("Count_Revolving"));
                    ruleInNextStep.setCrsaccountsummariescreditlimitinstallment(accountSummaries.getString("CreditLimit_Installment"));
                    ruleInNextStep.setCrsaccountsummariescreditlimitauto(accountSummaries.getString("CreditLimit_Auto"));
                    ruleInNextStep.setCrsaccountsummariescreditlimitmortgage(accountSummaries.getString("CreditLimit_Mortgage"));
                    ruleInNextStep.setCrsaccountsummariescreditlimitother(accountSummaries.getString("CreditLimit_Other"));
                    ruleInNextStep.setCrsaccountsummariescreditlimitoverdraft(accountSummaries.getString("CreditLimit_Overdraft"));
                    ruleInNextStep.setCrsaccountsummariescreditlimitrevolving(accountSummaries.getString("CreditLimit_Revolving"));
                    ruleInNextStep.setCrsaccountsummariespaymentinstallment(accountSummaries.getString("Payment_Installment"));
                    ruleInNextStep.setCrsaccountsummariespaymentauto(accountSummaries.getString("Payment_Auto"));
                    ruleInNextStep.setCrsaccountsummariespaymentmortgage(accountSummaries.getString("Payment_Mortgage"));
                    ruleInNextStep.setCrsaccountsummariespaymentother(accountSummaries.getString("Payment_Other"));
                    ruleInNextStep.setCrsaccountsummariespaymentrevolving(accountSummaries.getString("Payment_Revolving"));
                    ruleInNextStep.setCrsaccountsummariesbalancetotal(accountSummaries.getString("Balance_Total"));
                    ruleInNextStep.setCrsaccountsummariescounttotal(accountSummaries.getString("Count_Total"));
                    ruleInNextStep.setCrsaccountsummariescreditlimittotal(accountSummaries.getString("CreditLimit_Total"));
                    ruleInNextStep.setCrsaccountsummariespaymenttotal(accountSummaries.getString("Payment_Total"));
                }
            }
        }

        List<Date> accountStatusDateList = new ArrayList<>();
        List<Date> dateOpenedList = new ArrayList<>();

        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setGroupingUsed(false);

        JSONArray accountsArray = JSONArray.parseArray(ctcustomerCrsReport.getAccounts());
        if (accountsArray != null && accountsArray.size() > 0) {

            ruleInNextStep.setCrsaccountsnothing("0");

            Set<Object> ownerRegistryIDSet = new HashSet<>();
            Set<Object> crscntaccountnumSet = new HashSet<>();
            Map<String, Integer> crsmaxcntaccountnumMap = new HashMap<>();
            int crsmaxcreditlimit = -1;
            BigDecimal crsmaxinstalmentamount = new BigDecimal(0);
            double balanceMax = 0;
            double crsopenclosedateMax = -1;
            int crsopenmacth90d = 0;
            int crsopenmacth60d = 0;
            int crsopenmacth30d = 0;

            int crscreditmacth90d = 0;
            int crscreditmacth60d = 0;
            int crscreditmacth30d = 0;

            int crsclosemacth90d = 0;
            int crsclosemacth60d = 0;
            int crsclosemacth30d = 0;

            int crsperformingmacth90d = 0;
            int crsperformingmacth60d = 0;
            int crsperformingmacth30d = 0;

            int crsoverduelessthan30days90d = 0;
            int crsoverduelessthan30days60d = 0;
            int crsoverduelessthan30days30d = 0;

            int crsoverdueover3090days90d = 0;
            int crsoverdueover3090days60d = 0;
            int crsoverdueover3090days30d = 0;

            int crsriskaccountnum90d = 0;
            int crsriskaccountnum60d = 0;
            int crsriskaccountnum30d = 0;

            double crsbalanceamount90d = 0;
            double crsbalanceamount60d = 0;
            double crsbalanceamount30d = 0;

            for (int i = 0; i < accountsArray.size(); i++) {
                JSONObject accounts = accountsArray.getJSONObject(i);

                Date accountStatusDate = accounts.getDate("Account_Status_Date");
                Date dateOpened = accounts.getDate("Date_Opened");
                Date balanceDate = accounts.getDate("Balance_Date");

                accountStatusDateList.add(accountStatusDate);
                dateOpenedList.add(dateOpened);

                double diffTemp = DateUtils.getDateDiff(DateUtils.DATE_INTERVAL_DAY, accountStatusDate, dateOpened);
                crsopenclosedateMax = diffTemp > crsopenclosedateMax ? diffTemp : crsopenclosedateMax;

                //crscntaccountnumSet去重
                if (!crscntaccountnumSet.contains(accounts.get("Account_No"))) {
                    String key = accounts.get("Account_Owner_Registry_ID") + "";

                    crsmaxcntaccountnumMap.put(key, crsmaxcntaccountnumMap.get(key) == null ? 1 : crsmaxcntaccountnumMap.get(key) + 1);

                    double openMacthDay = DateUtils.getDateDiff(DateUtils.DATE_INTERVAL_DAY, ctcustomerCrsReport.getCreateTime(), dateOpened);
                    if (openMacthDay <= 90) {
                        crsopenmacth90d++;
                    }
                    if (openMacthDay <= 60) {
                        crsopenmacth60d++;
                    }
                    if (openMacthDay <= 30) {
                        crsopenmacth30d++;
                    }

                    double creditMacthDay = DateUtils.getDateDiff(DateUtils.DATE_INTERVAL_DAY, ctcustomerCrsReport.getCreateTime(), accountStatusDate);
                    if (creditMacthDay <= 90) {
                        crscreditmacth90d++;
                    }
                    if (creditMacthDay <= 60) {
                        crscreditmacth60d++;
                    }
                    if (creditMacthDay <= 30) {
                        crscreditmacth30d++;
                    }

                    String accountStatusId = accounts.getString("Account_Status_ID");

                    if ("999".equals(accountStatusId)) {
                        if (creditMacthDay <= 90) {
                            crsclosemacth90d++;
                        }
                        if (creditMacthDay <= 60) {
                            crsclosemacth60d++;
                        }
                        if (creditMacthDay <= 30) {
                            crsclosemacth30d++;
                        }
                    }

                    if ("0".equals(accountStatusId)) {
                        if (creditMacthDay <= 90) {
                            crsperformingmacth90d++;
                        }
                        if (creditMacthDay <= 60) {
                            crsperformingmacth60d++;
                        }
                        if (creditMacthDay <= 30) {
                            crsperformingmacth30d++;
                        }
                    }

                    //逾期
                    if ("29".equals(accountStatusId)) {
                        if (creditMacthDay <= 90) {
                            crsoverduelessthan30days90d++;
                        }
                        if (creditMacthDay <= 60) {
                            crsoverduelessthan30days60d++;
                        }
                        if (creditMacthDay <= 30) {
                            crsoverduelessthan30days30d++;
                        }
                    }

                    if (StringUtils.equalsAny(accountStatusId, "30", "60")) {
                        if (creditMacthDay <= 90) {
                            crsoverdueover3090days90d++;
                        }
                        if (creditMacthDay <= 60) {
                            crsoverdueover3090days60d++;
                        }
                        if (creditMacthDay <= 30) {
                            crsoverdueover3090days30d++;
                        }
                    }

                    if (StringUtils.equalsAny(accountStatusId, "90", "120", "150", "180", "360", "700", "701", "900")) {
                        if (creditMacthDay <= 90) {
                            crsriskaccountnum90d++;
                        }
                        if (creditMacthDay <= 60) {
                            crsriskaccountnum60d++;
                        }
                        if (creditMacthDay <= 30) {
                            crsriskaccountnum30d++;
                        }
                    }

                }

                double balanceDateDay = DateUtils.getDateDiff(DateUtils.DATE_INTERVAL_DAY, ctcustomerCrsReport.getCreateTime(), balanceDate);
                double balance = accounts.getDouble("Balance");
                if (balanceDateDay <= 90) {
                    crsbalanceamount90d += balance;
                }
                if (balanceDateDay <= 60) {
                    crsbalanceamount60d += balance;
                }
                if (balanceDateDay <= 30) {
                    crsbalanceamount30d += balance;
                }

                ownerRegistryIDSet.add(accounts.get("Account_Owner_Registry_ID"));
                crscntaccountnumSet.add(accounts.get("Account_No"));

                Integer creditLimit = accounts.getInteger("Credit_Limit");
                if (creditLimit != null) {
                    crsmaxcreditlimit = creditLimit > crsmaxcreditlimit ? creditLimit : crsmaxcreditlimit;
                }

                BigDecimal minimumInstallment = accounts.getBigDecimal("Minimum_Installment");
                if (minimumInstallment != null) {
                    crsmaxinstalmentamount = minimumInstallment.compareTo(crsmaxinstalmentamount) == 1 ? minimumInstallment : crsmaxinstalmentamount;
                }


                balanceMax = balance > balanceMax ? balance : balanceMax;
            }

            IntSummaryStatistics max5 = crsmaxcntaccountnumMap.entrySet().stream().collect(Collectors.summarizingInt(Map.Entry::getValue));

            ruleInNextStep.setCrsmaxcntaccountnum(max5.getMax() + "");
            ruleInNextStep.setCrscntloanenquiry(ownerRegistryIDSet.size() + "");
            ruleInNextStep.setCrscntaccountnum(crscntaccountnumSet.size() + "");
            ruleInNextStep.setCrsmaxcreditlimit(crsmaxcreditlimit + "");
            ruleInNextStep.setCrsmaxinstalmentamount(crsmaxinstalmentamount + "");

            ruleInNextStep.setCrsmaxcurrentbalanceamt(numberFormat.format(balanceMax));
            ruleInNextStep.setCrsopenclosedate(new BigDecimal(crsopenclosedateMax).divide(new BigDecimal("30"), 0, BigDecimal.ROUND_UP) + "");
            ruleInNextStep.setCrsopenmacth90d(crsopenmacth90d + "");
            ruleInNextStep.setCrsopenmacth60d(crsopenmacth60d + "");
            ruleInNextStep.setCrsopenmacth30d(crsopenmacth30d + "");

            ruleInNextStep.setCrscreditmacth90d(crscreditmacth90d + "");
            ruleInNextStep.setCrscreditmacth60d(crscreditmacth60d + "");
            ruleInNextStep.setCrscreditmacth30d(crscreditmacth30d + "");

            ruleInNextStep.setCrsclosemacth90d(crsclosemacth90d + "");
            ruleInNextStep.setCrsclosemacth60d(crsclosemacth60d + "");
            ruleInNextStep.setCrsclosemacth30d(crsclosemacth30d + "");

            ruleInNextStep.setCrsperformingmacth90d(crsperformingmacth90d + "");
            ruleInNextStep.setCrsperformingmacth60d(crsperformingmacth60d + "");
            ruleInNextStep.setCrsperformingmacth30d(crsperformingmacth30d + "");

            ruleInNextStep.setCrsoverduelessthan30days90d(crsoverduelessthan30days90d + "");
            ruleInNextStep.setCrsoverduelessthan30days60d(crsoverduelessthan30days60d + "");
            ruleInNextStep.setCrsoverduelessthan30days30d(crsoverduelessthan30days30d + "");

            ruleInNextStep.setCrsoverdueover3090days90d(crsoverdueover3090days90d + "");
            ruleInNextStep.setCrsoverdueover3090days60d(crsoverdueover3090days60d + "");
            ruleInNextStep.setCrsoverdueover3090days30d(crsoverdueover3090days30d + "");

            ruleInNextStep.setCrsriskaccountnum90d(crsriskaccountnum90d + "");
            ruleInNextStep.setCrsriskaccountnum60d(crsriskaccountnum60d + "");
            ruleInNextStep.setCrsriskaccountnum30d(crsriskaccountnum30d + "");

            ruleInNextStep.setCrsbalanceamount90d(numberFormat.format(crsbalanceamount90d));
            ruleInNextStep.setCrsbalanceamount60d(numberFormat.format(crsbalanceamount60d));
            ruleInNextStep.setCrsbalanceamount30d(numberFormat.format(crsbalanceamount30d));


            if (accountStatusDateList.size() > 0 && dateOpenedList.size() > 0) {
                double dateDiff = DateUtils.getDateDiff(DateUtils.DATE_INTERVAL_DAY, Collections.max(accountStatusDateList), Collections.min(dateOpenedList));
                ruleInNextStep.setCrsupdatedopendate(new BigDecimal(dateDiff).divide(new BigDecimal("30"), 0, BigDecimal.ROUND_UP) + "");
            }

        } else {
            ruleInNextStep.setCrsaccountsnothing("1");
        }

        List<Integer> crspaymentprofilesm3List = new ArrayList<>();
        List<Integer> crspaymentprofilesm6List = new ArrayList<>();
        List<Integer> crspaymentprofilesm12List = new ArrayList<>();
        List<Integer> crspaymentprofilesm24List = new ArrayList<>();
        List<Integer> crspaymentprofileslg0m6List;
        List<Integer> crspaymentprofileslg0m12List;
        List<Integer> crspaymentprofileslg0m24List;

        JSONArray paymentProfilesArray = JSONArray.parseArray(ctcustomerCrsReport.getPaymentProfiles());
        if (paymentProfilesArray != null) {
            for (int i = 0; i < paymentProfilesArray.size(); i++) {
                JSONObject paymentProfile = paymentProfilesArray.getJSONObject(i);
                String paymentProfileStr = paymentProfile.getString("PaymentProfile");
                if (paymentProfileStr != null) {
                    crspaymentprofilesm3List.add(getPaymentProfileData(paymentProfileStr, 0));
                    crspaymentprofilesm3List.add(getPaymentProfileData(paymentProfileStr, 1));
                    crspaymentprofilesm3List.add(getPaymentProfileData(paymentProfileStr, 2));
                    crspaymentprofilesm6List.add(getPaymentProfileData(paymentProfileStr, 3));
                    crspaymentprofilesm6List.add(getPaymentProfileData(paymentProfileStr, 4));
                    crspaymentprofilesm6List.add(getPaymentProfileData(paymentProfileStr, 5));
                    crspaymentprofilesm12List.add(getPaymentProfileData(paymentProfileStr, 6));
                    crspaymentprofilesm12List.add(getPaymentProfileData(paymentProfileStr, 7));
                    crspaymentprofilesm12List.add(getPaymentProfileData(paymentProfileStr, 8));
                    crspaymentprofilesm12List.add(getPaymentProfileData(paymentProfileStr, 9));
                    crspaymentprofilesm12List.add(getPaymentProfileData(paymentProfileStr, 10));
                    crspaymentprofilesm12List.add(getPaymentProfileData(paymentProfileStr, 11));
                    crspaymentprofilesm24List.add(getPaymentProfileData(paymentProfileStr, 12));
                    crspaymentprofilesm24List.add(getPaymentProfileData(paymentProfileStr, 13));
                    crspaymentprofilesm24List.add(getPaymentProfileData(paymentProfileStr, 14));
                    crspaymentprofilesm24List.add(getPaymentProfileData(paymentProfileStr, 15));
                    crspaymentprofilesm24List.add(getPaymentProfileData(paymentProfileStr, 16));
                    crspaymentprofilesm24List.add(getPaymentProfileData(paymentProfileStr, 17));
                    crspaymentprofilesm24List.add(getPaymentProfileData(paymentProfileStr, 18));
                    crspaymentprofilesm24List.add(getPaymentProfileData(paymentProfileStr, 19));
                    crspaymentprofilesm24List.add(getPaymentProfileData(paymentProfileStr, 20));
                    crspaymentprofilesm24List.add(getPaymentProfileData(paymentProfileStr, 21));
                    crspaymentprofilesm24List.add(getPaymentProfileData(paymentProfileStr, 22));
                    crspaymentprofilesm24List.add(getPaymentProfileData(paymentProfileStr, 23));
                }

            }
            crspaymentprofilesm6List.addAll(crspaymentprofilesm3List);
            crspaymentprofilesm12List.addAll(crspaymentprofilesm6List);
            crspaymentprofilesm24List.addAll(crspaymentprofilesm12List);

            ruleInNextStep.setCrspaymentprofilesm3(crspaymentprofilesm3List.size() == 0 ? "0" : Collections.max(crspaymentprofilesm3List) + "");
            ruleInNextStep.setCrspaymentprofilesm6(crspaymentprofilesm6List.size() == 0 ? "0" : Collections.max(crspaymentprofilesm6List) + "");
            ruleInNextStep.setCrspaymentprofilesm12(crspaymentprofilesm12List.size() == 0 ? "0" : Collections.max(crspaymentprofilesm12List) + "");
            ruleInNextStep.setCrspaymentprofilesm24(crspaymentprofilesm24List.size() == 0 ? "0" : Collections.max(crspaymentprofilesm24List) + "");

            crspaymentprofileslg0m6List = crspaymentprofilesm6List.stream().filter(s -> s > 0).collect(Collectors.toList());
            crspaymentprofileslg0m12List = crspaymentprofilesm12List.stream().filter(s -> s > 0).collect(Collectors.toList());
            crspaymentprofileslg0m24List = crspaymentprofilesm24List.stream().filter(s -> s > 0).collect(Collectors.toList());

            ruleInNextStep.setCrspaymentprofileslg0m6(crspaymentprofileslg0m6List.size() + "");
            ruleInNextStep.setCrspaymentprofileslg0m12(crspaymentprofileslg0m12List.size() + "");
            ruleInNextStep.setCrspaymentprofileslg0m24(crspaymentprofileslg0m24List.size() + "");

        }

        //2021-10-8
        JSONArray smartScoresArray = JSONArray.parseArray(ctcustomerCrsReport.getSmartScores());
        if (Func.isNotEmpty(smartScoresArray)) {
            List<JSONObject> smartScores = smartScoresArray.toJavaList(JSONObject.class);
            Map<Object, Object> enquiryMap = smartScores.stream().collect(Collectors.toMap(e -> e.get("Registry_ID"), e -> e));
            ruleInNextStep.setCrscntenquiry(enquiryMap.size() + "");
        }

        return afterFormatRuleInNextStepCrs(ruleInNextStep);
    }

    private static RuleInNextStepCrs afterFormatRuleInNextStepCrs(RuleInNextStepCrs ruleInNextStep) {

        ruleInNextStep = RuleUtils.afterFormat(ruleInNextStep, "crsId", "nextStepId");

        if ("-1".equals(ruleInNextStep.getState())) {
            ruleInNextStep.setState(UserConstants.BUSINESS_NORMAL);
        }
        return ruleInNextStep;
    }


    public static Integer getPaymentProfileData(String str, int index) {

        if (StringUtils.isBlank(str) || str.length() <= index + 1) {
            return -1;
        }
        String substring = str.substring(index, index + 1);
        if ("N".equals(substring)) {
            return -1;
        } else {
            return Integer.parseInt(substring);
        }
    }


}
